home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / packet / p_tapr / kissv7 / kiss_v7.mac < prev    next >
Text File  |  1991-06-27  |  49KB  |  1,887 lines

  1. ;
  2. ;             KISS TNC for the TNC-2 and clones
  3. ;
  4. ; k3mc 30 Sep 86 - original version
  5. ;
  6. ; 1 Mar 87.  Fixed all known bugs.  Re-arrange code to allow ROMing (this
  7. ; means that data areas need to be initialized from the code).  Figure out the
  8. ; Stack Pointer given the amount of available RAM.  Include the codes 05 00
  9. ; and 05 01 to mean full duplex off and full duplex on, respectively.
  10. ; Clear out all available RAM.  Do a "dance" with LEDs when initially booted:
  11. ; Flash the LED(s) for about 5 seconds such that CON only flashes if you have
  12. ; 8k RAM, STA only flashes if 16k RAM, and STA and CON flash if 32k RAM.
  13. ;
  14. ; 29 Mar 87. Add code to discard BREAK chars, and chars with framing errors.
  15. ; Fix bug in ib_rca which did not discard null received frames.
  16. ;
  17. ; 11 Dec 89.  Incorporate code from Jan Schiefer, DL5UE, [44.130.48.9]
  18. ; Degerlocherstrasse 5, 7000 Stuttgart 70, Federal republic of Germany
  19. ; to fix the problem with Full-Duplex operation.  New version number, v.4
  20. ;
  21. ; 19 Jan 91. Shin-ichi Kanno , JN1JDZ , [133.168.32.129]
  22. ; Fix the DCD detection problem. Add the auto-enable operation.
  23. ; Add the code of output following data routine. New version number, v.5
  24. ;
  25. ; 27 Jun 91. Add the TXdelay control . Fix buffer allocation problem .
  26. ; Add the code of Software DCD Detection routine. New version number, v.7
  27. ;
  28.  
  29. FALSE    equ    0
  30. TRUE    equ    NOT FALSE
  31.  
  32. ALONE    equ    TRUE    ;uncomment this line to get stand-alone code. 
  33.  
  34. ;TASCO    equ    TRUE    ;uncomment this line to get for TASCO's TNC's
  35.             ;(TNC-20,TNC-20H and TNC-22) ROM code.
  36.  
  37. SIO_AUTO    equ    TRUE    ;uncomment this line to set SIO PORT B for
  38.                 ;auto-enable mode.
  39.  
  40. HARDWARE    equ    TRUE    ;uncomment this line to add the set hardware
  41.                 ;sub command.
  42.  
  43.  
  44. ;    .z80
  45. ;    aseg
  46. ;    org    100h    ;silly stuff for CP/M...
  47.  
  48.     ifdef    ALONE
  49.             .phase    0000h
  50. Free_RAM        equ    8000h
  51.     else
  52.         ifdef    TASCO
  53.             .phase    7000h
  54. Free_RAM        equ    0d000h
  55.         else
  56.             .phase    7800h
  57. Free_RAM        equ    9000h
  58.         endif
  59.     endif
  60.  
  61. SIO    equ    0dch        ;actually, only A5 is used for SIO -cs
  62.  
  63. A_dat    equ    SIO+0    ;Modem port
  64. A_ctl    equ    SIO+1    ;Modem port
  65.  
  66. B_dat    equ    SIO+2    ;user serial port
  67. B_ctl    equ    SIO+3    ;user serial port
  68.  
  69. DCD    equ    8        ;Bit in RR0, used in Ch A
  70. CTS    equ    32        ;Bit in RR0, used in Ch A
  71.  
  72. TBE    equ    4        ;TX Buffer Empty bit
  73. RTS    equ    2        ;Request To Send (PTT bit in WR5 of Chan A)
  74.  
  75. Framing_Error    equ    40h    ;Bit in RR1 for async framing error
  76. Break_Abort    equ    80h    ;Bit in RR0 for async Break detection
  77.  
  78.     ifdef SIO_AUTO
  79. Auto_Enable    equ    0e1h
  80.     else
  81. Auto_Enable    equ    0c1h
  82.     endif
  83.  
  84. FEND    equ    300o        ;300 octal
  85. FESC    equ    333o        ;333 octal
  86. TFEND    equ    334o        ;334 octal
  87. TFESC    equ    335o        ;335 octal
  88.  
  89. ALEDon    equ    69h        ;bits for WR5 to turn on  STA LED
  90. ALEDoff    equ    0e9h        ;bits for WR5 to turn off STA LED
  91.  
  92. ALED    equ    80h        ;The DTR Bit in Ch A WR5, we will soon remove
  93.                 ;previous 2 definitions & use the memory loc.
  94.                 ;A_WR5 to hold Ch A WR5's value, because we
  95.                 ;need to be aware when we are transmitting!
  96.  
  97. BLEDon    equ    6ah        ;bits for WR5 to turn on  CON LED
  98. BLEDoff    equ    0eah        ;bits for WR5 to turn off CON LED
  99. BLED    equ    80h
  100.  
  101. start:
  102.     jp    code_start    ;go around this data area
  103. version:
  104.     db    'v.7 27 Jun 91'
  105.     ;13 bytes (exactly!) here for version string
  106.  
  107. I_Vector:
  108.     dw    ib_tbe    ;ch B transmitter buffer empty interrupt/user
  109.     dw    ib_ext    ;ch B ext/status change/user
  110.     dw    ib_rca    ;ch B received char available/user
  111.     dw    ib_special    ;ch B special receive condition/user
  112.  
  113.     dw    ia_tbe    ;ch A transmitter buffer empty interrupt/modem
  114.     dw    ia_ext    ;ch A ext/status change/modem
  115.     dw    ia_rca    ;ch A received char available/modem
  116.     dw    ia_special    ;ch A special receive condition/modem
  117.  
  118. code_start:
  119.     di                ;No interrupts for the moment...
  120.  
  121. ;Init SIO.  This is required even if we wanna flash LEDs...
  122.  
  123.     in    a,(A_ctl)        ;assure we are talking to ch 0
  124.     ld    c,A_ctl
  125.     ld    b,a_size
  126.     ld    hl,a_init
  127.     otir                ;init sync (modem) port
  128.  
  129. ;Init Async port, also to allow flashing LEDs
  130.  
  131.     in    a,(B_ctl)        ;assure we are talking to ch 0
  132.     ld    c,B_ctl
  133.     ld    b,b_size
  134.     ld    hl,b_init
  135.     otir                ;init async port & interrupt vector
  136.  
  137. ; Figure out where top of stack is, set stack pointer.
  138. ; 32K RAM system.
  139.  
  140.     ld    sp,0            ;[JDZ]
  141.  
  142. ;Clear out RAM.
  143.  
  144.     ld    bc,0ffffh-Free_RAM-1    ;[JDZ] get Byte Count into BC
  145.     ld    hl,Free_RAM        ;[JDZ]
  146.     ld    (hl),0            ;[JDZ]
  147.     ld    de,Free_RAM+1        ;[JDZ] get "source" address = Free_RAM
  148.  
  149.     ldir                ;Zero memory.
  150.  
  151. ;This sequence loads up our data area in RAM:
  152.  
  153.     ld    hl,data_init
  154.     ld    de,TXdelay
  155.     ld    bc,data_size
  156.     ldir
  157.  
  158.  
  159. ; init free buffer list.
  160.  
  161.     ld    hl,Bottom        ;[JDZ] beginning of buffer space
  162.                     ;[JDZ] now it's also top of free list
  163.     ld    b,-1+(-100-Bottom)/128    ;[JDZ] get buffers - 1
  164. ibloop:
  165.     push    hl
  166.     ld    de,128
  167.     add    hl,de            ;HL has "next" pointer
  168.     ex    de,hl            ;DE has "next" pointer
  169.     pop    hl            ;HL now has pointer to current buffer
  170.  
  171.     ld    (hl),e            ;low byte of "next" pointer first
  172.     inc    hl
  173.     ld    (hl),d            ;now hi byte
  174.     inc    hl
  175.     xor    a
  176.     ld    (hl),a            ;zero out count field
  177.     inc    hl
  178.     ld    (hl),a            ;zero out # of bytes read field
  179.  
  180.     ex    de,hl            ;HL is now pointer to next buffer
  181.     djnz    ibloop            ;and init all the available buffers
  182.  
  183.     xor    a
  184.     ld    (hl),a            ;Last "next" address is 0
  185.     inc    hl
  186.     ld    (hl),a            ;ditto
  187.  
  188.     inc    hl
  189.     ld    (hl),a            ;zero out count field
  190.     inc    hl
  191.     ld    (hl),a            ;zero out # of bytes read field
  192.  
  193. ;init regs for ib_ext interrupt
  194.     exx
  195.     ld    bc,0            ;set prev state of SYNC pin,for 1200hz
  196.     ld    de,0            ;count of # of interrupts init
  197.     exx
  198.  
  199. ;[JDZ] Now have the CON and STA LEDs do a "dance".
  200.  
  201.     ld    b,6        ;Do it 6 times (arbitrary as hell, but should
  202.                 ;be an even number so that the LEDs are off at
  203.                 ;the end of this mess...)
  204.     ld    hl,0        ;use HL as downcounter
  205. dance0:
  206.     call    CON_Flip
  207.     call    STA_Flip
  208. dance1:
  209.     dec    hl
  210.     ld    a,h
  211.     or    l
  212.     jr    nz,dance1
  213.  
  214.     djnz    dance0        ;do this 6 times  (3 "cycles")
  215.  
  216. ;Previous stuff showed that the download or boot worked properly...
  217.  
  218.  
  219.  
  220. ;We re-initialize the SIO ports so that we flush garbage chars that may have
  221. ;come in while we were diddling the LEDs.  This is necessary because unless we
  222. ;do this, then the A channel (modem) get RX overrun (esp if TNC was listening
  223. ;to noise) and RX overrun is VERY BAD - so bad, in fact, that I turn on both
  224. ;CON and STA and halt, because this situation should NEVER happen in normal
  225. ;use.  I flush the B (tty) channel in case anything was sent to it in mid-
  226. ;stream.
  227.  
  228.  
  229. ;Re-Init SIO.
  230.  
  231.     in    a,(A_ctl)        ;assure we are talking to ch 0
  232.     ld    c,A_ctl
  233.     ld    b,a_size
  234.     ld    hl,a_init
  235.     otir                ;init sync (modem) port
  236.  
  237. ;Re-Init Async port.
  238.  
  239.     in    a,(B_ctl)        ;assure we are talking to ch 0
  240.     ld    c,B_ctl
  241.     ld    b,b_size
  242.     ld    hl,b_init
  243.     otir                ;init async port & interrupt vector
  244.  
  245. ; Prepare to load hi bits of interrupt vector
  246.  
  247.     ld    a,I_Vector/256
  248.     ld    i,a            ;set interrupt page for mode 2 ints
  249.     im    2
  250.     ei                ;let 'em rip!
  251.  
  252. ;-----------------------------------------------------------------------------
  253. ; This is the background program.
  254. ; Note that since everything else is interrupt driven, and saves registers,
  255. ; this part of the code can use registers & expect values to stay.
  256.  
  257. Commutator_loop:
  258.     call    TX_data
  259.     call    Host_TX_data
  260.     jp    Commutator_loop
  261.  
  262. ;Now see if we need to start an output to RS-232 (host) port
  263. Host_TX_data:
  264.     ld    a,(out_started)
  265.     or    a            ;also clears carry (see below) 
  266.     ret    nz            ;if output started, nothing to do
  267.  
  268.     in    a,(B_ctl)        ;look at RR0
  269.     and    TBE            ;isolate the TBE bit
  270.     ret    z
  271.  
  272. ; else we should check to see if we need to start an output
  273.     di
  274.     call    CON_off            ;
  275.     ld    hl,(out_head_cbuf)    ;grab current top of circ buf ptr
  276.     ld    de,(out_tail_cbuf)    ;and where the next free buf ptr is
  277.     ei
  278.                     ;interrupt protect the pickup of the
  279.                     ;two pointers 3 Feb 87
  280.     or    a
  281.     sbc    hl,de
  282.     ret    z            ;if the same, nothing to do
  283.  
  284. ;else we need to start an output
  285.     di                ;interrupt protect this section,
  286.                     ;although I'm not sure it needs it...
  287.                     ;3 Feb 87
  288.                     ;note: it should already BE done!
  289.     ld    hl,(out_head_cbuf)    ;get pointer to next cbuf to output
  290.     ld    e,(hl)
  291.     inc    hl
  292.     ld    d,(hl)            ;DE has pointer to buffer chain
  293.     ld    (out_chain_head),de    ;set in interrupt routine's place
  294.     ld    a,TRUE
  295.     ld    (out_started),a        ;yes, output started
  296.  
  297.     call    CON_on    
  298.  
  299.     ld    a,FEND
  300.     out    (B_dat),a        ;send FEND character (start txing)
  301.     ei
  302.  
  303.     ret                ;keep looking for new opportunity
  304.  
  305. TX_data:
  306.     ld    a,(TX_State)
  307.     or    a
  308.     jp    z,txd0
  309.     cp    1
  310.     jp    z,txd1
  311.     cp    2
  312.     jp    z,txd2
  313.     cp    3
  314.     jp    z,txd3
  315.     cp    4
  316.     ret    z
  317.  
  318. ;When tail timer times out, turn off the TX
  319.  
  320.     ld    a,(TX_Timer)
  321.     or    a
  322.     ret    nz
  323.  
  324.     ld    a,5        ;ready to write to WR5 of Ch A
  325.     di            ;must have atomic use of A_WR5 & SIO
  326.     out    (A_ctl),a    ;Next char to A_ctl goes to WR5
  327.     ld    a,(A_WR5)    ;grab A_WR5
  328.     and    NOT RTS        ;turn off RTS bit there
  329.     ld    (A_WR5),a    ;keep memory copy updated
  330.     out    (A_ctl),a    ;and turn off TX now
  331.     xor    a
  332.     ld    (TX_State),a
  333.     ei
  334.     ret
  335.  
  336. txd0:
  337.     ld    a,(TX_outstanding)    ;if there are no outstanding TX...
  338.     or    a            ;...frames, then we don't have to...
  339.     ret    z            ;...worry about Transmitter
  340.  
  341. ; do persistence algorithm
  342.     ld    a,r            ;grab the Z-80 refresh register
  343.     add    a,a            ;double;now 0 <= A reg <= 254
  344.     ld    b,a            ;B holds our "random" number
  345.     ld    a,(Persistence)
  346.     sub    b            ;A reg = Persistence - Random #
  347.     jp    c,No_PTT        ;if (P-r) < 0 then no PTT now
  348.                     ; Note that P=255 means ALWAYS key up
  349.  
  350. ; else we've noticed that we've got some frame(s) to send.
  351. ; try to keyup TX
  352.  
  353.     ld    a,(Full_Duplex)
  354.     or    a
  355.     jp    nz,Key_Up        ;if Full Duplex, then there is no
  356.                     ;need to worry about all this silly
  357.                     ;slot time and persistence stuff!
  358.  
  359.     ifdef    HARDWARE
  360. ;check soft DCD.
  361.     ld    a,(Soft_DCD)
  362.     ld    l,a
  363.     bit    1,l
  364.     jp    z,txd1a
  365.  
  366.     ld    a,(RX_State)
  367.     or    a
  368.     jp    nz,No_PTT
  369.  
  370. ;check if Carrier Detect is active
  371. txd1a:
  372.     bit    0,l
  373.     jp    z,Key_Up
  374.  
  375.     endif
  376.  
  377.     ld    a,(A_RR0)        ;A_RR0 is set in interrupt routine
  378.     and    DCD
  379.     jp    nz,No_PTT        ;[JDZ] If carrier active, wait it out
  380.  
  381. ;OK, so we've won with the random number generator.  Keyup TX and start the
  382. ;TXdelay timer
  383.  
  384. Key_Up:
  385.     ld    a,(TXdelay)
  386.     ld    (TX_Timer),a        ;Get timer value into timer slot
  387.  
  388.     ld    a,5
  389.     di                ;we need quite time here.
  390.     out    (A_ctl),a        ;Ready to write into WR5 of Ch A
  391.     ld    a,(A_WR5)
  392.     or    RTS            ;Turn on the PTT bit...
  393.     ld    (A_WR5),a        ;...in the memory copy of WR5
  394.     out    (A_ctl),a        ; Keyup transmitter
  395.     ld    a,2
  396.     ld    (TX_State),a
  397.     ei
  398.     ret                ;That's all we do for now, we await
  399.                     ;TXdelay event
  400.  
  401. No_PTT:    ;since we lost on Random #, wait SlotTime before trying again
  402.     ld    a,(SlotTime)
  403.     ld    (TX_Timer),a        ;Set up the timer value of this event
  404.     ld    a,1
  405.     ld    (TX_State),a
  406.     ret
  407.  
  408. txd1:
  409.     ld    a,(TX_Timer)
  410.     or    a
  411.     ret    nz
  412.     xor    a
  413.     ld    (TX_State),a
  414.     ret
  415.  
  416. txd2:
  417.     ld    a,(TX_Timer)
  418.     or    a
  419.     ret    nz
  420.     ld    a,3
  421.     ld    (TX_State),a
  422.     ret
  423.  
  424. txd3:
  425.     ifdef    HARDWARE
  426. ;    CTS flow
  427.     ld    a,(CTS_Control)
  428.     or    a
  429.     jp    z,txd3a
  430.  
  431.     ld    a,(A_RR0)
  432.     and    CTS
  433.     ret    z
  434. txd3a:
  435.     endif
  436.     di
  437.  
  438.     ld    a,4
  439.     ld    (TX_State),a
  440.  
  441.     call    TXnext_CBuf        ;gets HL to point to buffer chain, and
  442.                     ;sets TX_Chain_Head for the interrupt
  443.                     ;routine
  444.     ld    a,80h
  445.     out    (A_ctl),a        ; reset TX CRC
  446.     call    getchar            ; getchar needs int. protection
  447.     out    (A_dat),a        ; Ship this char to TX modem
  448.     ld    a,TRUE
  449.     ld    (TX_Started),a    ; and, yes Virgina, we've started TX
  450.     ld    a,0c0h
  451.     out    (A_ctl),a        ; reset TX underrun/EOM latch
  452.  
  453.     ei
  454.     ret
  455.  
  456.  
  457. ;    include    IA.MAC            ;Modem interrupt catchers
  458. ;---------------------------------------------------------------------------
  459. ia_tbe:
  460.     push    af
  461.     push    hl
  462.     ld    a,(TX_Started)
  463.     or    a
  464.     jp    z,ia_t2        ; previous frame finished
  465.  
  466.     ld    hl,(TX_Chain_Head)
  467.     call    getchar
  468.     ld    (TX_Chain_Head),hl    ; must keep this pointer updated
  469.     jp    z,ia_t1        ; no more to send
  470.  
  471.     out    (A_dat),a        ; else ship this char out
  472. ia_t9:
  473.     pop    hl
  474.     pop    af
  475.     ei
  476.     reti                ; just return from these interrupts
  477.  
  478. ia_t1:
  479. ;    halt                ;if it gets here, halt
  480.     xor    a
  481.     ld    (TX_Started),a    ; TX is NOT started
  482.     ld    hl,TX_Outstanding    ; make is so that one fewer frames
  483.                     ; NOT "(TX_Outstanding)" (!) 29 Sep
  484.     dec    (hl)            ; are outstanding
  485.     ld    a,28h
  486.     out    (A_ctl),a        ; reset TX interrupt pending
  487.     jp    ia_t9
  488.  
  489. ;previous frame is done, SIO now sending a flag.  More?
  490. ia_t2:
  491.     ld    a,(TX_Outstanding)
  492.     or    a
  493.     jp    nz,ia_t21        ;if more to send, go there
  494.  
  495. ; else we're done here, clean up.
  496.     ld    a,28h
  497.     out    (A_ctl),a        ; Reset TX interrupt pending
  498.  
  499. ;start Tail timer event
  500.     ld    a,(TailTime)
  501.     ld    (TX_Timer),a        ; wait for CRC to clear TX
  502.     ld    a,5
  503.     ld    (TX_State),a
  504.     jp    ia_t9
  505.  
  506. ia_t21:            ;start up next frame
  507.     call    TXnext_CBuf        ; get the next buffer chain pointer
  508.                     ; setup HL and TX_Chain_Head
  509.     ld    a,80h
  510.     out    (A_ctl),a        ; reset TX CRC generator
  511.     call    getchar
  512.     out    (A_dat),a        ;get 1st char of next frame
  513.     ld    a,TRUE
  514.     ld    (TX_Started),a    ; TX started again
  515.     ld    a,0c0h
  516.     out    (A_ctl),a        ; reset TX underrun/EOM latch
  517.     jp    ia_t9
  518.  
  519. ;---------------------------------------------------------------------------
  520. ; Got a character from the SIO RX interrupt, deal with it
  521. ; Extensive mods 3 Feb 87 to be in line with what I now know about SIO...
  522.  
  523. ia_rca:
  524.     push    af
  525.     push    hl
  526.  
  527.     ld    a,(RX_flushing)
  528.     or    a
  529.     jp    z,ia_rc1
  530.  
  531.     in    a,(A_dat)
  532.     jp    ia_rc9
  533.  
  534. ia_rc1:
  535.     ld    a,(RX_Allocated_Buffer)
  536.     or    a
  537.     jp    nz,ia_rc7    ; Go there if we are in "receiving" state
  538.  
  539. ;else we are not yet receiving, so allocate buffer & make us "receiving"
  540.  
  541.     call    allocate_buffer    ; get a new buffer
  542.     jp    z,ia_rc5    ; NO ROOM, flush this frame
  543.  
  544. ; if got a buffer, insert this character.
  545. ; after doing initial buffer setup.
  546.  
  547. ia_rc6:
  548.     ld    (RX_head),hl    ; save chain head address (1st buffer)
  549.     ld    (RX_buf),hl    ; tuck away addr of our current buffer
  550.     ld    a,TRUE
  551.     ld    (RX_Allocated_Buffer),a    ; and mark that
  552.                         ; we are receiving
  553.  
  554.     ld    a,0        ; Channel 0
  555.     call    putchar        ; SLIP' frame "type" field here (Always 0)
  556.  
  557. ia_rc7:
  558.     in    a,(A_dat)    ; grab the pending character
  559.     ld    hl,(RX_buf)    ; load up address of our current RX buffer
  560.     call    putchar        ; and stuff in this particular buffer
  561.     jp    c,ia_rc2    ; If NO ROOM, flush this frame.
  562.     ld    (RX_buf),hl    ; HL might have changed in putchar()
  563.  
  564. ia_rc9:
  565.     pop    hl
  566.     pop    af
  567.  
  568.     ei
  569.     reti                ; nothing else to do here
  570.  
  571.  
  572. ; if no room, flush this frame (sigh)
  573. ia_rc2:
  574.     xor    a
  575.     ld    (RX_Allocated_Buffer),a
  576.     ld    hl,(RX_head)
  577.     call    free_chain
  578. ia_rc5:
  579.     ld    a,TRUE
  580.     ld    (RX_flushing),a    ; we are in the midst of
  581.                     ; flushing this frame
  582.     call    STA_on            ;ddd Note that we are in flushing
  583.                     ;state
  584.     jp    ia_rc9
  585.  
  586. ;---------------------------------------------------------------------------
  587. ; From out point of view, this interrupt is only interesting because it
  588. ; tells us if we're at end of frame.
  589. ia_special:
  590.     push    af
  591.     push    hl        ; regs we'll need
  592.  
  593.     ld    a,1
  594.     out    (A_ctl),a    ; ready to read RR1
  595.     in    a,(A_ctl)    ; OK, grab RR1
  596.  
  597. ; First check if RX overrun.  This is VERY BAD, so what can we do?
  598. ; Well, we merely treat it as a bad CRC, that is, just flushing the
  599. ; frame.  I don't like dropping chars (and it shouldn;t happen very often)
  600. ; but at high speeds, it may occur with 2.5 MHz z80s.
  601.  
  602.     bit    5,a        ; RX overrun?
  603.     jp    nz,ia_sp8    ; If a problem, treat as bad CRC
  604.                 ; That is, flush this frame....
  605. ;ia_sp0:
  606.     bit    7,a        ; check state of End of Frame bit
  607.     jp    z,ia_sp8    ; Else something weird happened - probably
  608.                 ; RX overrun. In any case, flush this frame.
  609.                 ; error reset & then exit
  610.                 ; that is, treat like it was a CRC error
  611.  
  612. ; If End of Frame, check CRC bit for valid.
  613. ia_sp1:
  614.     bit    6,a        ; Check CRC error bit
  615.     jp    nz,ia_sp8    ; If CRC error bit is on, then was CRC error
  616.  
  617. ; First ensure that we indeed have a buffer allocated...
  618.     ld    a,(RX_Allocated_Buffer)
  619.     or    a
  620.     jp    z,ia_sp9    ; if no buffer allocated, ignore this.
  621.  
  622. ; Else this was a good frame, and we should ship it out to host
  623. ; Leave the first CRC character at end of buffer chain in the buffer, as
  624. ; getchar() will flush it.
  625.  
  626.     ld    hl,(RX_head)
  627.     call    out_queue_insert    ; Shove this buffer string onto
  628.                     ; output queue
  629.     xor    a
  630.     ld    (RX_Allocated_Buffer),a    ; We don't have a buffer
  631.                         ; allocated for the next
  632.                         ; frame...
  633.     jp    ia_sp9
  634.  
  635. ; get here if there was a bad CRC
  636. ia_sp8:
  637.     ld    a,(RX_Allocated_Buffer)    ; If we don't have any
  638.                         ; buffers allocated, then
  639.     or    a        ;8 Feb - SET CONDITION CODES !!!!!!
  640.     jp    z,ia_sp9    ; we MUST NOT "release" them !!! 10 Sep 86
  641.                 ; if they are not allocated !!!
  642.     xor    a
  643.     ld    (RX_Allocated_Buffer),a
  644.                 ; not receiving if we have bad CRC
  645.     ld    hl,(RX_head)
  646.     call    free_chain    ; free up all buffer(s)
  647.  
  648. ia_sp9:
  649.     ld    a,30h        ; error reset
  650.     out    (A_ctl),a
  651.     in    a,(A_dat)    ; Avoid spurious RCA interrupt
  652.  
  653.     ld    a,03h        ; [JS] select WR3
  654.     out    (A_ctl),a    ; [JS]
  655.     ld    a,0D9h        ; [JS] enter hunt mode
  656.     out    (A_ctl),a    ; [JS]
  657.     xor    a
  658.     ld    (RX_State),a    ; [JS] store sync/hunt state
  659.     ld    (RX_flushing),a
  660.  
  661.     ifdef    HARDWARE
  662. ; Software DCD filetr
  663.     ld    a,(Full_Duplex)
  664.     or    a
  665.     jp    nz,ia_spsd
  666.  
  667.     ld    a,(TX_State)
  668.     cp    2
  669.     jp    nc,ia_spsd
  670.  
  671.     ld    a,(Soft_DCD)
  672.     bit    1,a
  673.     jp    z,ia_spsd
  674.  
  675.     ld    a,1
  676.     ld    (TX_State),a
  677.     ld    a,(SlotTime)
  678.     ld    (TX_Timer),a
  679. ia_spsd:
  680.  
  681.     endif
  682.  
  683.     pop    hl
  684.     pop    af
  685.  
  686.     ei
  687.     reti
  688.  
  689. ;---------------------------------------------------------------------------
  690. ; for ext/status interrupts on Modem, get DCD state into memory, and
  691. ; deallocate any spurious buffers (buffer stuff done 30 Sep 86).
  692. ia_ext:
  693.     push    af
  694.     ld    a,10h        ; reset ext/status interrupts
  695.     out    (A_ctl),a
  696.     in    a,(A_ctl)    ; grab RR0
  697.     ld    (A_RR0),a
  698.     bit     4,a             ; [JS] check sync/hunt bit
  699.     jp      nz,ia_ex1    ; [JS] no need to worry, if not zero
  700.     ld      a,(RX_State)    ; [JS] it is 0! Did it change?
  701.     or      a               ; [JS]
  702.     jp      nz,ia_ex9    ; [JS] no, this is a DCD,CTS or EOM-interrupt
  703.     ld    a,TRUE        ; [JS] indeed, it changed!
  704.     ld      (RX_State),a    ; [JS] next time, we'll know
  705.  
  706.     ld    a,(RX_Allocated_Buffer)    ; if we are not in the
  707.                         ; receiving state...
  708.     or    a        ; then there are no allocated buffers and...
  709.     jp    z,ia_ex9    ; we MUST NOT "release" them !!! 10 Sep 86
  710.                 ; if no buffers allocated !!!
  711.     xor    a
  712.     ld    (RX_Allocated_Buffer),a    ; not receiving
  713.     push    hl
  714.     ld    hl,(RX_head)
  715.     call    free_chain            ; free up all buffer(s)
  716.     pop    hl
  717.     jp    ia_ex9
  718. ia_ex1:
  719.     xor    a        ; [JS] Prepare for next frame start
  720.     ld    (RX_State),a    ; [JS]
  721.     ld    (RX_flushing),a
  722. ia_ex9:
  723.     pop     af
  724.     ei
  725.     reti
  726.  
  727.  
  728. ;    include    IB.MAC            ;TTY interrupt catchers
  729.  
  730. ;---------------------------------------------------------------------------
  731. ; we get here whenever -cts, -dcd or -sync inputs change, as well as break
  732. ; detection. Since -dcd
  733. ; is always tied to +5 volts, we need only worry about -cts and -sync.
  734. ; -cts is wired to pin 20, DTR, of the RS232 connector, and is supposed to
  735. ; be used for host to TNC handshaking; we ignore this transition (We assume
  736. ; that the host is always ready).  We also ignore break detection.  We are
  737. ; only interested in -sync transitions, so we can keep time.
  738. ; NOTE!  This is the ONLY routine that is allowed to use the other reg set!!
  739. ; deal with break detection...
  740.  
  741. sync_hunt    equ    10h
  742. ib_ext:
  743.     ex    af,af'
  744.     exx            ; we want the other registers
  745.     ld    a,10h
  746.     out    (B_ctl),a    ; reset ext/status interrupts
  747.     in    a,(B_ctl)    ; grab RR0
  748.     ld    d,a        ; Hold it for a moment...
  749.     and    sync_hunt    ; isolate this bit
  750.     jp    z,ib_s0
  751. ;else sync/hunt is a 1
  752.     ld    a,c
  753.     or    a
  754.     jp    z,ib_s1    ; go here if state of sync/hunt changed
  755.  
  756.  
  757. ; Here if sync/hunt bit did NOT change - maybe something else did....
  758. ib_s9:
  759.     ld    a,d        ; retreive RRO from above
  760.     and    Break_Abort    ; Check if we are doing a break/abort thing
  761.     jp    z,ib_NBA    ; There if No break/abort
  762.  
  763. ; Else Break/Abort bit on, note state change...
  764.     ld    a,TRUE
  765.     ld    (in_break),a    ; save in mem  (probably can use E reg...)
  766.     in    a,(B_dat)    ; clear out any null character from buffer
  767.     jp    ib_BOK    ; Break OK for now...
  768.  
  769. ib_NBA:    ;if no break/abort, check if we are in break/abort state.
  770.     ld    a,(in_break)
  771.     or    a
  772.     jp    z,ib_BOK    ; Nothing going on, Break OK
  773.  
  774. ; Else we were in break mode, and this is the tail end of a break.
  775.     xor    a
  776.     ld    (in_break),a
  777.     in    a,(B_dat)    ; discard the single extraneous null
  778. ib_BOK:
  779. ib_s99:
  780.     ex    af,af'
  781.     exx
  782.     ei
  783.     reti            ; else something else & we don't care
  784. ib_s0:            ; sync/hunt is a 0
  785.     ld    a,c
  786.     or    a
  787.     jp    nz,ib_s1a    ; go here if sync/hunt changed
  788.     jp    ib_s9    ; else not interested, forget it
  789.  
  790. ;get here if state of sync/hunt changed
  791. ib_s1:
  792.     ld    c,1
  793.     jp    ib_s1b
  794. ib_s1a:                ; first fix up C for next tick
  795.     ld    c,0
  796. ib_s1b:
  797. ; Here when we've seen a real "clock tick" & dealt with C reg
  798.     inc    b
  799.     ld    a,b
  800.     cp    12
  801.     jp    nz,ib_s99        ; we act on every 12th clock tick...
  802.     ld    b,0            ; so reload divisor. This give us an
  803.                     ; effective interrupt rate of 100 Hz
  804.  
  805. ; Decrement all the timers
  806.  
  807.     ld    a,(TX_Timer)        ; Get value, and ...
  808.     or    a
  809.     jp    z,ib_s1c
  810.     dec    a            ; ... decrement it as required.
  811.     ld    (TX_Timer),a
  812. ib_s1c:
  813.     jp    ib_s99
  814.  
  815.  
  816. ;---------------------------------------------------------------------------
  817. ib_special:
  818.     push    af
  819. ib_sp9:            ; Normal exit
  820.     ld    a,30h        ; error reset
  821.     out    (B_ctl),a
  822.     pop    af
  823.     ei
  824.     reti
  825.  
  826. ;---------------------------------------------------------------------------
  827. ; The TX has become empty, shove a new character out
  828. ib_tbe:
  829.     push    af        ; new char will return in A
  830.     push    hl
  831.  
  832.     ld    a,(Out_esc_mode)
  833.     or    a
  834.     jp    z,ib_t1    ; not escaped, so go here
  835. ; else we are escaped, so send escaped char
  836.     ld    a,(Out_char)    ; char which follows escape
  837.     or    a
  838.     jp    z,ib_t2    ; special case if at end of frame, clean up
  839.     out    (B_dat),a
  840.     xor    a
  841.     ld    (Out_esc_mode),a    ; get out of escaped mode
  842.     jp    ib_t9        ; all for now...
  843. ib_t1:
  844.     ld    hl,(out_chain_head)    ; we are currently on this buffer,
  845.     call    getchar            ; as getchar() needs to know
  846.     ld    (out_chain_head),hl    ; maybe HL changed,so save it in case
  847.  
  848.     jp    z,ib_tdone    ; if no more chars, deal with this
  849.     cp    FESC
  850.     jp    z,ib_t1a    ; deal with FESC char in data stream
  851.     cp    FEND
  852.     jp    z,ib_t1b    ; deal with FEND char in data stream
  853. ; else this char is nothing special, so shove it out
  854.  
  855.     out    (B_dat),a    ; shove it out
  856.     jp    ib_t9    ; if this is not last char, all for now
  857.  
  858. ; else this is last char, send FEND
  859. ib_tdone:
  860.     ld    a,FEND
  861.     out    (B_dat),a
  862.     ld    a,TRUE
  863.     ld    (Out_esc_mode),a    ; set special escaped mode by...
  864.     xor    a
  865.     ld    (Out_char),a        ;... making escaped char a 0
  866.     jp    ib_t9        ; all till TX Buffer goes empty again.
  867.  
  868. ; here if are completely done sending frame
  869. ib_t2:
  870.     push    de        ; need this for a moment
  871.     ld    hl,(out_head_cbuf)
  872.     inc    hl
  873.     inc    hl        
  874.     ld    de,out_bottom
  875.     or    a
  876.     push    hl
  877.     sbc    hl,de
  878.     pop    hl            ; this may be the one we want
  879.     pop    de
  880.     jp    nz,ib_t2a        ; yes it is!
  881.  
  882.     ld    hl,Out_Top        ; else, make a circular buffer
  883. ib_t2a:
  884.     ld    (out_head_cbuf),hl    ; we will work on this one next
  885.     xor    a
  886.     ld    (out_started),a        ; not doing outputs anymore
  887.     ld    (Out_esc_mode),a    ; !! NOT IN ESCAPED MODE ANYMORE !!
  888.  
  889.     ld    a,28h            ; NEEDED for ASYNC
  890.     out    (B_ctl),a        ; reset TX interrupt pending
  891.  
  892. ib_t9:
  893.     pop    hl
  894.     pop    af
  895.     ei
  896.     reti                ; now get our butts out of here...
  897.  
  898. ; here is FESC in data stream
  899. ib_t1a:
  900.     out    (B_dat),a        ; Ship FESC character to port
  901.     ld    a,TFESC            ; ready what will be next char
  902. ib_t1z:
  903.     ld    (Out_char),a        ; set char for next time
  904.     ld    a,TRUE
  905.     ld    (Out_esc_mode),a    ; we are in escaped mode
  906.     jp    ib_t9        ; all for now
  907.  
  908. ; here is FEND in data stream
  909. ib_t1b:
  910.     ld    a,FESC
  911.     out    (B_dat),a
  912.     ld    a,TFEND
  913.     jp    ib_t1z        ; rest is same as FESC case
  914.  
  915.  
  916. ;---------------------------------------------------------------------------
  917. ; Got a char from the TTY port, deal with it.
  918.  
  919. ib_rca:
  920.     push    af
  921.  
  922.     in    a,(B_ctl)    ; Read RR0; force reg pointer to be 0
  923.     ld    a,1
  924.     out    (B_ctl),a    ; ready to read RR1
  925.     in    a,(B_ctl)    ; Grab RR1
  926.     and    Framing_Error    ; Isolate the FE bit
  927.     jp    z,ib_Rtop    ; No Framing Error, so process this char
  928.  
  929. ; Else we have a Framing Error - Ignore this char & flush this frame...
  930.     call    STA_off        ; Off with the LED!
  931.     in    a,(B_dat)    ; Flush erroneous character
  932.     xor    a
  933.     ld    (In_state),a    ; Force receiver to look for FEND
  934.     ld    a,(In_Allocated_Buffer)
  935.     or    a
  936.     jp    z,ib_rc9    ; If no buffer is allocated, done; Exit.
  937.  
  938. ; Else we were receiving a data SLIP frame, so flush it.
  939.     push    hl
  940.     ld    hl,(In_head)
  941.     call    free_chain    ; Dump these buffers back to free list
  942.     pop    hl
  943.     jp    ib_rc9    ; And get out of here!
  944.  
  945. ib_rTop:
  946.     ld    a,(In_state)    ; get our state machine value
  947.     or    a
  948.     jp    z,ib_r0    ; in state 0, waiting for FEND
  949.     cp    1
  950.     jp    z,ib_r1    ; in state 1, saw FEND
  951.     cp    2
  952.     jp    z,ib_r2    ; in state 2, data to follow
  953.     cp    3
  954.     jp    z,ib_r3    ; saw FESC, expecting TFESC or TFEND
  955.     cp    10
  956.     jp    z,ib_r10    ; Expecting TXdelay
  957.     cp    20
  958.     jp    z,ib_r20    ; Expecting P value
  959.     cp    30
  960.     jp    z,ib_r30    ; Expecting SlotTime value
  961.     cp    40
  962.     jp    z,ib_r40    ; Expecting TailTime value
  963.     cp    50
  964.     jp    z,ib_r50    ; Expecting Full/Half duplex value
  965.  
  966.     ifdef    HARDWARE
  967.  
  968.     cp    60
  969.     jp    z,ib_r60    ;[JDZ] Expecting Set Hardware value
  970.  
  971.     ifndef    TASCO
  972.     cp    61
  973.     jp    z,ib_r61    ;[JDZ] Expecting Set Hardware value
  974.     endif
  975.  
  976.     endif
  977. ;else we don't know what happened, ignore it.
  978. ib_rcjunk:
  979.     in    a,(B_dat)
  980. ib_rcFEND:
  981.     xor    a
  982. ib_rcSTATE:
  983.     ld    (In_State),a    ;go into In_State 0, FEND hunt
  984. ib_rc9:
  985.     pop    af        ; throw it away, we don't need junk
  986.     ei
  987.     reti
  988.  
  989. ; Here if we are hunting for FEND character
  990. ib_r0:
  991.     call    STA_off
  992.  
  993.     in    a,(B_dat)
  994.     cp    FEND
  995.     jp    nz,ib_rc9    ; if we didn't see an FEND, keep looking
  996.  
  997. ; else is an FEND, change state
  998.     ld    a,1
  999.     jp    ib_rcSTATE
  1000.  
  1001. ; Get here if we've seen FEND character; look for command byte
  1002. ib_r1:
  1003.     call    STA_off
  1004.     in    a,(B_dat)
  1005.     cp    FEND
  1006.     jp    z,ib_rc9    ; Just another FEND, keep looking for cmd
  1007.  
  1008.     call    STA_on        ;getting valid SLIP; show in STA LED
  1009.  
  1010. ; Here if we DO NOT have an FEND (expecting command byte)
  1011.     ifndef    ALONE
  1012.         cp    0ffh
  1013.         jp    z,kiss_exit
  1014.     endif
  1015.  
  1016.     and    0fh
  1017.     jp    z,ib_r1a    ; 0 command means data will follow
  1018.     cp    1
  1019.     jp    z,ib_r1b    ; 1 command means TXdelay will follow
  1020.     cp    2
  1021.     jp    z,ib_r1c    ; 2 command means P(Persistence) will follow
  1022.     cp    3
  1023.     jp    z,ib_r1d    ; 3 command means Slot Time will follow
  1024.     cp    4
  1025.     jp    z,ib_r1e    ; 4 command means TailTime to follow
  1026.     cp    5
  1027.     jp    z,ib_r1f    ; 5 command means Full/Half duplex to come
  1028.  
  1029.     ifdef    HARDWARE
  1030.  
  1031.     cp    6
  1032.     jp    z,ib_r1g    ; 6 command means Set Hardware to come
  1033.  
  1034.     endif
  1035.  
  1036. ; Here if we receive bogus command byte, flush rest of frame
  1037.  
  1038.     call    STA_off        ;bogosity, so turn off STA LED
  1039.  
  1040.     jp    ib_rcFEND
  1041.  
  1042. ; exit kiss mode.
  1043.     ifndef    ALONE
  1044. kiss_exit:
  1045.         ld    hl,(000eh)
  1046.         res    4,(hl)
  1047.         ld    hl,0000h
  1048.         push    hl
  1049.         ld    hl,(0019h)
  1050.         jp    (hl)
  1051.     endif
  1052.  
  1053. ; Data are expected, change state
  1054. ib_r1a:
  1055.     ld    a,2
  1056.     jp    ib_rcSTATE
  1057.  
  1058. ; TXdelay to follow, change state
  1059. ib_r1b:
  1060.     ld    a,10
  1061.     jp    ib_rcSTATE
  1062.  
  1063. ; P to follow, change state
  1064. ib_r1c:
  1065.     ld    a,20
  1066.     jp    ib_rcSTATE
  1067.  
  1068. ; SlotTime to follow, change state
  1069. ib_r1d:
  1070.     ld    a,30
  1071.     jp    ib_rcSTATE
  1072.  
  1073. ; TailTime to follow, change state
  1074. ib_r1e:
  1075.     ld    a,40
  1076.     jp    ib_rcSTATE
  1077.  
  1078. ; Full/Half Duplex to follow, change state
  1079. ib_r1f:
  1080.     ld    a,50
  1081.     jp    ib_rcSTATE
  1082.  
  1083.     ifdef    HARDWARE
  1084. ; Set Hardware to follow, change state
  1085. ib_r1g:
  1086.     ld    a,60
  1087.     jp    ib_rcSTATE
  1088.     endif
  1089.  
  1090. ; These bytes are data
  1091. ib_r2:
  1092.     in    a,(B_dat)
  1093.     cp    FEND
  1094.     jp    z,ib_r2b    ; FEND means to queue this buffer
  1095.     push    af        ; Save the char we read on stack for a bit..
  1096.  
  1097.     ld    a,(In_Allocated_Buffer)
  1098.     or    a
  1099.     jp    nz,ib_r2c    ; if we already allocated buffer
  1100.  
  1101.     push    hl
  1102.     call    allocate_buffer    ; get our initial buffer to mess with
  1103.     jp    nz,ib_r22
  1104.  
  1105. ; else no room, flush this frame
  1106.     pop    af
  1107.     pop    hl        ; keep stack tidy
  1108.     jp    ib_rcFEND
  1109.  
  1110. ib_r22:
  1111.     ld    a,TRUE
  1112.     ld    (In_Allocated_Buffer),a    ; make ourselves active
  1113.  
  1114.     ld    (In_buffer),hl
  1115.     ld    (In_head),hl    ; save current & head of chain pointers
  1116.     pop    hl
  1117.  
  1118. ib_r2c:
  1119.     pop    af        ; Retreive the data char we just got...
  1120.     cp    FESC
  1121.     jp    z,ib_r2a    ; If FESC in data stream, switch state
  1122.  
  1123.     push    hl
  1124.     ld    hl,(In_buffer)
  1125.     call    putchar        ; shove this character into our buffer
  1126.     jp    nc,ib_r2ca
  1127.  
  1128.     xor    a
  1129.     ld    (In_Allocated_buffer),a
  1130.     ld    hl,(In_head)
  1131.     call    free_buffer
  1132.     pop    hl
  1133.     jp    ib_rcFEND
  1134.  
  1135. ib_r2ca:
  1136.     ld    (In_buffer),hl    ; save in case HL changed
  1137.     pop    hl
  1138.     jp    ib_rc9    ; done so far
  1139.  
  1140.  
  1141. ; FESC character seen while grabbing data
  1142. ib_r2a:
  1143.     ld    a,3
  1144.     jp    ib_rcSTATE
  1145.  
  1146. ; FEND character seen while grabbing data
  1147. ib_r2b:
  1148.     ld    a,(In_Allocated_Buffer)
  1149.     or    a
  1150.     jp    z,ib_r2z    ; No bytes accumulated, so is null frame
  1151.  
  1152. ; else we must ship this frame to TX
  1153.     push    hl        ; This bug found 29 Sep (must save HL !!!)
  1154.     ld    hl,(In_Buffer)
  1155.     call    putchar        ; put a garbage character at the end of
  1156.                 ; last buffer because getchar() will strip
  1157.                 ; it. Hack needed because of RX use of
  1158.                 ; putchar/getchar.
  1159.     ld    hl,(In_head)
  1160.     jp    nc,ib_r2za
  1161.     call    free_chain
  1162.     jp    ib_r2zb
  1163. ib_r2za:
  1164.     call    TX_queue_insert
  1165. ib_r2zb:
  1166.     pop    hl
  1167.     xor    a
  1168.     ld    (In_Allocated_Buffer),a    ; input no longer active
  1169. ib_r2z:                ; entry point for null frame
  1170.     call    STA_off        ;done getting this frame, turn STA LED off
  1171.     ld    a,1        ; Keep as was, FENDs only at end in v.32
  1172.  
  1173.     jp    ib_rcSTATE
  1174.  
  1175.  
  1176.  
  1177. ; here if we've seen FESC in data stream
  1178. ib_r3:
  1179.     in    a,(B_dat)
  1180.     cp    TFESC
  1181.     jp    z,ib_r3a
  1182.     cp    TFEND
  1183.     jp    z,ib_r3b
  1184.  
  1185. ; Else we don't know what the hell it is, so ignore & keep collecting bytes
  1186.     ld    a,2
  1187.     jp    ib_rcSTATE
  1188.  
  1189. ; here if we've seen TFESC after an FESC in data stream; write an FESC
  1190. ib_r3a:
  1191.     ld    a,FESC
  1192. ib_r3z:
  1193.     push    hl
  1194.     ld    hl,(In_buffer)
  1195.     call    putchar
  1196.     jp    nc,ib_r3za
  1197.  
  1198.     xor    a
  1199.     ld    (In_Allocated_buffer),a
  1200.     ld    hl,(In_head)
  1201.     call    free_buffer
  1202.     pop    hl
  1203.     jp    ib_rcFEND
  1204.  
  1205. ib_r3za:
  1206.     ld    (In_buffer),hl
  1207.     pop    hl
  1208.     ld    a,2
  1209.     jp    ib_rcSTATE
  1210.  
  1211. ; Here if we've seen TFEND after FESC in data stream; write FEND
  1212. ib_r3b:
  1213.     ld    a,FEND
  1214.     jp    ib_r3z        ; rest is same as for TFESC case
  1215.  
  1216. ; This character is interpreted as TXdelay
  1217. ib_r10:
  1218.     in    a,(B_dat)
  1219.     ld    (TXdelay),a
  1220.     jp    ib_rcFEND
  1221.  
  1222. ; This charcter is P, Persistence value
  1223. ib_r20:
  1224.     in    a,(B_dat)
  1225.     ld    (Persistence),a
  1226.     jp    ib_rcFEND
  1227.  
  1228. ; This character is SlotTime value
  1229. ib_r30:
  1230.     in    a,(B_dat)
  1231.     ld    (SlotTime),a
  1232.     jp    ib_rcFEND
  1233.  
  1234.  
  1235. ; This character is TailTime value
  1236. ib_r40:
  1237.     in    a,(B_dat)
  1238.     ld    (TailTime),a
  1239.     jp    ib_rcFEND
  1240.  
  1241.  
  1242. ; This character is Full/Half Duplex value
  1243. ; 0 means Half Duplex, non-zero means Full Duplex
  1244. ib_r50:
  1245.     in    a,(B_dat)
  1246.     ld    (Full_Duplex),a
  1247.     jp    ib_rcFEND
  1248.  
  1249.     ifdef    HARDWARE
  1250. ; This character is Set Hardware value
  1251. ; data means Output Address.
  1252. ib_r60:
  1253.     in    a,(B_dat)
  1254.     cp    0feh        ; CTS flow off
  1255.     jp    nc,ib_r60cts
  1256.     cp    0fch        ; Reserved
  1257.     jp    nc,ib_rcFEND
  1258.     cp    0f8h        ; DCD
  1259.     jp    nc,ib_r60DCD
  1260.  
  1261.     ifndef    TASCO
  1262.     cp    020h
  1263.     jp    nc,ib_rcFEND
  1264.     add    a,0a0h        ; A5=1 OUT_DATA address, Ch A
  1265.     ld    (Out_Address),a
  1266.     ld    a,61
  1267.     jp    ib_rcSTATE
  1268.     else
  1269.     jp    ib_rcFEND
  1270.     endif
  1271.  
  1272. ;    CTS flow
  1273. ib_r60cts:
  1274.     sub    0feh
  1275.     ld    (CTS_Control),a
  1276.     jp    ib_rcFEND
  1277.  
  1278. ;    Software DCD
  1279. ib_r60dcd
  1280.     sub    0f8h
  1281.     ld    (Soft_DCD),a
  1282.     jp    ib_rcFEND
  1283.  
  1284.     ifndef    TASCO
  1285. ; data means Output Data.
  1286. ib_r61:
  1287.     push    bc
  1288.     ld    a,(Out_Address)
  1289.     ld    c,a
  1290.     in    a,(B_dat)
  1291.     out    (c),a
  1292.     pop    bc
  1293.     jp    ib_rcFEND
  1294.     endif
  1295.  
  1296.     endif
  1297.  
  1298. ;    include    BUFFERS.MAC        ;all buffer-related stuff in here
  1299.                     ;plus all (eventually) variables
  1300. ;
  1301. ; The buffer list is kept from "bottom" to the end of RAM.  The format of the
  1302. ; buffers is:
  1303. ;+------+--------+-------+---------------------------------------------------+
  1304. ;| next | Nbytes | Nread | data                             |
  1305. ;+------+--------+-------+---------------------------------------------------+
  1306. ;
  1307. ; 2 bytes 1 byte   1 byte  124 bytes  (Total 128 bytes)
  1308. ; next     Pointer to next buffer on this buffer chain (or 0 if no more)
  1309. ; Nbytes Number of bytes in this buffer that are valid
  1310. ; Nread  Number of bytes read from this buffer (used by getchar)
  1311. ; data   124 bytes of data (not all is necessarily valid, see Nbytes field)
  1312. ;
  1313. ; The buffer pool is all here, and as processes need buffer space, it is all
  1314. ; allocated out of this pool.  See allocate_buffer and free_buffer code.
  1315.  
  1316.  
  1317. ;---------------------------------------------------------------------------
  1318. ; return in HL a pointer to a free buffer.  If there are not more buffers,
  1319. ; return with Z flag set.
  1320. ; destroys no registers except return value HL.
  1321. ; IS CALLED FROM AN INTERRUPT ROUTINE, so this operation is atomic.
  1322.  
  1323. allocate_buffer:
  1324.  
  1325.     push    bc
  1326.     push    af
  1327.  
  1328.     ld    hl,(free)        ;get pointer to head of free list
  1329.     ld    a,h
  1330.     or    l
  1331.     jp    nz,OK_allocate_buffer    ; assure we're not off the end
  1332.  
  1333. ;get here if no more buffers.  Return Z set - do not disturb A.
  1334.     pop    af
  1335.     ld    b,a            ; tuck A away for a moment...
  1336.     xor    a            ; turn on Z bit
  1337.     ld    a,b            ; retreive original A
  1338.     pop    bc
  1339.     ret
  1340.  
  1341. OK_allocate_buffer:
  1342.  
  1343.     xor    a
  1344.     ld    c,(hl)            ;grab lo byte of next free buffer
  1345.     ld    (hl),a            ; clear it out
  1346.     inc    hl
  1347.     ld    b,(hl)            ; "ld bc,(hl)" now hi byte
  1348.     ld    (hl),a            ; clear it out, too
  1349.     ld    (free),bc        ; update with new free list pointer
  1350.  
  1351.     dec    hl            ; Now HL is at head of new buffer
  1352.  
  1353.     pop    af
  1354.     ld    b,a            ; tuck A away for a moment...
  1355.     ld    a,1
  1356.     or    a            ; Turn Z bit off (i.e., all OK)
  1357.     ld    a,b            ; retreive original A
  1358.  
  1359.     pop    bc
  1360.     ret
  1361.  
  1362. ;---------------------------------------------------------------------------
  1363. ; free_buffer gets passed a pointer (in HL) to a buffer to be freed.  The
  1364. ; buffer is placed on the head of the free list.  The nbytes & nread fields
  1365. ; are made 0 before placing on free list.
  1366. ; THIS ROUTINE IS CALLED AT INTERRUPT LEVEL, so results are atomic.
  1367. ; no registers are disturbed at all.  The FREE pointer is updated, however.
  1368. ; 159 T states [ 63.6 usec @ 2.5 MHz ]
  1369.  
  1370. free_buffer:
  1371.     push    af
  1372.     push    bc        ;we'll use these
  1373.     push    hl        ;this will be new head of free list
  1374.  
  1375.     ld    bc,(free)    ;get old free head
  1376.     ld    (hl),c        ;put on free chain, first low byte...
  1377.     inc    hl
  1378.     ld    (hl),b        ; ...now hi byte
  1379.     xor    a
  1380.     inc    hl
  1381.     ld    (hl),a        ; zero out nbytes field
  1382.     inc    hl
  1383.     ld    (hl),a        ; and the nread field of new head of free
  1384.  
  1385.     pop    hl        ;get new head of free list back
  1386.     ld    (free),hl    ;and save it in memory where it belongs
  1387.  
  1388.     pop    bc
  1389.     pop    af
  1390.     ret
  1391. ; --------------------------------------------------------------------------
  1392. ; putchar - HL contains pointer to buffer, A contains the character to put
  1393. ; into the buffer.  Upon return, char is put into this buffer if ther is
  1394. ; room, else another buffer is allocated and HL is updated to point to this
  1395. ; new buffer.  The new buffer is chained onto the old buffer in this case.
  1396. ; The calling routine is responsible for maintaing both the head of a
  1397. ; particular buffer chain (if it needs it), and the current buffer being
  1398. ; manipulated. THIS ROUTINE IS CALLED AT INTERRUPT LEVEL, so is atomic.  No
  1399. ; registers disturbed, except that HL may have a new value.
  1400. ; 211 T states [  84.4 usec @ 2.5 MHz ]    no new buffer required
  1401. ; 338 T states [ 135.2 usec @ 2.5 MHz ]    New buffer needed
  1402.  
  1403. ; [JDZ] If carry flag is on, then memory is not enough to putchar.
  1404.  
  1405. putchar:
  1406.     push    bc
  1407.     push    ix
  1408.     push    af
  1409.     push    hl        ;do it this way for a reason...
  1410.  
  1411.     pop    ix        ;get buffer pointer into IX
  1412.     ld    a,(ix+2)    ;grab nbytes field
  1413.     cp    124        ;max of 124 chars in a buffer
  1414.     jp    nz,putc1
  1415.     call    putc_need_new_buffer
  1416. ; if it takes this call, it returns with a new buffer, with HL pointing to
  1417. ; it (as well as IX), and with A reg set to 0.
  1418. ; else just plunk into buffer
  1419.     jp    nc,putc1
  1420.     pop    af
  1421.     scf
  1422.     jp    putc2
  1423. putc1:
  1424.     inc    (ix+2)        ;one more char will go into this buffer
  1425.     ld    c,a        ;get previous nbytes
  1426.     xor    a
  1427.     ld    b,a        ; bc <- nbytes, filled out to 16 bits
  1428.     add    ix,bc        ; update ix to point to where char goes
  1429.     pop    af        ; retreive the char we want to save
  1430.     ld    (ix+4),a    ; save it in this buffer
  1431.     or    a        ; reset Cy flag.
  1432. putc2:
  1433.     pop    ix
  1434.     pop    bc
  1435.     ret            ;done for the moment
  1436.  
  1437. ; 127 T states [ 50.8 usec @ 2.5 MHz ] (really part of prev routine)
  1438. putc_need_new_buffer:        ;prev buffer filled, get a new one
  1439.     push    de        ; working registers
  1440.     push    hl        ; save current buffer pointer
  1441.     call    allocate_buffer    ; grab a new buffer, addr is in HL
  1442.     jp    nz,putcnb1
  1443.     pop    hl
  1444.     scf
  1445.     jp    putcnb2
  1446. putcnb1:
  1447.     ex    de,hl        ; "ld de,hl" - get new addr into DE for now
  1448.     pop    hl
  1449.     ld    (hl),e        ; link new buffer onto chain, lo byte first
  1450.     inc    hl
  1451.     ld    (hl),d        ; now hi byte, chaining done
  1452.  
  1453.     ex    de,hl        ; update HL for orig. calling routine's use
  1454.     push    hl
  1455.     pop    ix        ; upper routine needs ix pointing to new buf
  1456.     xor    a        ; and A is nbytes in calling routine, make..
  1457.                 ; zero for a new buffer
  1458. putcnb2:
  1459.     pop    de        ; done with this working register
  1460.     ret            ; all done here, let calling routine finish
  1461.  
  1462. ; --------------------------------------------------------------------------
  1463. ; getchar - grab a character from the buffer pointed at by HL, return in A.
  1464. ; if the "nread" field of this buf = "nbytes" then this buffer is exhausted,
  1465. ; so follow the chain on to the next buffer & release old buffer.  If the
  1466. ; next chain is 0, or if the nbytes field is >= nread field, then there are
  1467. ; no more bytes.  In this case, return with Z bit set; normally return with
  1468. ; Z bit reset (That is, non-zero) indicating a valid char is in A.  Note
  1469. ; that if we need to follow the chain to a new buffer, HL will be updated,
  1470. ; too, so that the calling routine needs to deal with this.
  1471. ;         no registers changed except AF and possibly HL.
  1472. ; CALLED AT INTERRUPT LEVEL, so operation is atomic.
  1473. ; 212 T states [  84.8 usec @ 2.5 MHz ]    No new buffer needed
  1474. ; 493 T states [ 197.2 usec @ 2.5 MHz ]    if following chain
  1475.  
  1476. getchar:
  1477.     push    ix        ; save because is working reg
  1478.     push    bc        ; working regs here
  1479.  
  1480.     push    hl
  1481.     pop    ix        ; ix points to this buffer
  1482.  
  1483.     ld    a,(ix+3)    ; grab Nread
  1484.     cp    (ix+2)        ; compare with Nbytes
  1485.     call    z,getc_new_buf    ; if they are same, this buffer is spent
  1486.  
  1487.     inc    (ix+3)        ; we are reading one more char, update Nread
  1488.     inc    a
  1489.     cp    (ix+2)
  1490.     jp    nz,getc_pluck_character    ; if not looking at last character
  1491.  
  1492. ; else, is the "next" pointer 0?
  1493.     push    hl
  1494.     ld    b,a        ; !!!!! SAVE  A   REG  !!!!!!! 4 Jan 87
  1495.     ld    a,(hl)
  1496.     inc    hl
  1497.     or    (hl)
  1498.     ld    a,b        ; !!!! Restore A Reg  (Gasp!)
  1499.     pop    hl
  1500.     jp    nz,getc_pluck_character
  1501.  
  1502. ; else next is 0 and we are on last char - flush it & quit
  1503.     call    free_buffer
  1504.     pop    bc
  1505.     pop    ix
  1506.     ret            ; note that Z bit is set (from above)
  1507.  
  1508. ; else we can just pluck a character out of this buffer
  1509. getc_pluck_character:
  1510.     dec    a        ; fix A from above mucking around...
  1511.  
  1512.     ld    c,a        ; get old Nread into BC
  1513.     ld    b,0        ; ditto
  1514.     add    ix,bc        ; fix buffer pointer
  1515.     ld    a,1
  1516.     or    a        ; make Z bit reset
  1517.     ld    a,(ix+4)    ; get the desired byte
  1518.  
  1519.     pop    bc
  1520.     pop    ix
  1521.     ret            ; all for this simple case
  1522.  
  1523. ; old buffer is spent, get new one (if any)
  1524.  
  1525. getc_new_buf:
  1526.     push    de        ; need this reg here
  1527.     ld    e,(hl)        ; get lo byte of Next pointer
  1528.     inc    hl
  1529.     ld    d,(hl)        ; hi byte of Next pointer (now all in DE)
  1530.     dec    hl        ; HL now back to point at spent buffer
  1531.     call    free_buffer    ; give the buffer back
  1532.  
  1533.     ex    de,hl        ; "ld hl,de" - follow chain
  1534.     push    hl
  1535.     pop    ix        ; init new IX (same as HL in this routine)
  1536.     xor    a        ; A holds Nread (needed above)
  1537.     pop    de        ; release DE from use by this excursion
  1538.     ret
  1539.  
  1540. ; --------------------------------------------------------------------------
  1541. ; free_chain - MUST be called from interrupt routine to guarantee
  1542. ; atomicity.  Takes buffer chain pointed at by HL and returns them to free
  1543. ; buffer list
  1544. ; 303 T states + (n_on_chain-1)*238 T states
  1545. ; [ 121.2 usec + (n_on_chain-1)*95.2 usec ]
  1546.  
  1547. free_chain:
  1548.     push    af
  1549.     push    de
  1550.     push    hl        ; we will muck with these
  1551.  
  1552. fc_0:
  1553.     ld    e,(hl)        ; get lo part of next buffer pointer
  1554.     inc    hl
  1555.     ld    d,(hl)        ; now hi part of next buffer pointer
  1556.     dec    hl
  1557.     call    free_buffer    ; release this buffer
  1558.     ld    a,d
  1559.     or    e
  1560.     jp    z,fc_9        ; if "next" address is 0, we are at end
  1561. ; else we've got more on this chain - deal with them.
  1562.     ex    de,hl        ; "ld hl,de" - HL points to "next"
  1563.     jp    fc_0
  1564.  
  1565. fc_9:
  1566.     pop    hl
  1567.     pop    de
  1568.     pop    af
  1569.     ret
  1570.  
  1571. ; --------------------------------------------------------------------------
  1572. ; out_queue_insert - Places the just-received buffer on the output queue.
  1573. ; The address of the RX buffer just received is in HL.
  1574. ; The output queue is a circular buffer.  The output routine keeps sending
  1575. ; out buffers until its out_head_cbuf pointer equals its out_tail_cbuf
  1576. ; pointer. The output routine never mucks with the out_tail_cbuf pointer;
  1577. ; similarly, this routine never changes the out_head_cbuf pointer.  So it
  1578. ; is possible to
  1579. ; insert new entries into the output circular buffer queue without
  1580. ; disturbing the entry which is being sent to the output port.
  1581.  
  1582. out_queue_insert:
  1583.     push    af
  1584.     push    de
  1585.     push    hl        ; use these
  1586.  
  1587.     ex    de,hl        ; "ld de,hl" - move buffer to link addr
  1588.     ld    hl,(out_tail_cbuf) ; Grab next free location 
  1589.     ld    (hl),e        ; set lo addr 1st
  1590.     inc    hl
  1591.     ld    (hl),d        ; now hi addr
  1592.     inc    hl        ; Now HL points to next free entry in...
  1593.     ld    de,out_bottom    ; ...circ buf, unless we're at end
  1594.     or    a        ; clear carry
  1595.     push    hl        ; (may be be needed address)
  1596.     sbc    hl,de
  1597.     pop    hl        ; get back what we think is good
  1598.     jp    nz,oqi_0
  1599.     
  1600.     ld    hl,Out_Top    ; get here if we're at end of circ buffer.
  1601. oqi_0:
  1602.     ld    (out_tail_cbuf),hl
  1603.     pop    hl
  1604.     pop    de
  1605.     pop    af        ; keep clean
  1606.     ret
  1607.  
  1608.  
  1609. ;---------------------------------------------------------------------------
  1610. ; TX_Queue_Insert - similar to Out_queue_insert, but with different queue.
  1611. ; Also, increments the byte TX_Outstanding (which counts the number of
  1612. ; frames ready to be dumped to the modem port).  This routine, like
  1613. ; out_queue_insert, does not need to worry about queue wrap-around because
  1614. ; there are more entries in each of these queues than there are buffers
  1615. ; available.  Yes, I know this is a hack, and wastes some RAM space, but it
  1616. ; means I don't have to check for overflows here.
  1617. ; The queue is circular, and sometimes I call it a "CBuf" - Circular Buffer
  1618.  
  1619. TX_Queue_Insert:
  1620.     push    af
  1621.     push    de
  1622.     push    hl
  1623.     ex    de,hl            ; "ld de,hl" - save chain head in DE
  1624.     ld    hl,(TX_Tail_CBuf)    ; Next free location in TX CBuf
  1625.     ld    (hl),e
  1626.     inc    hl
  1627.     ld    (hl),d            ; put this chain into TX Queue
  1628.     inc    hl            ; HL is next availble TX Queue ...
  1629.     ld    de,TX_Bottom        ; ... unless we are at bottom of ...
  1630.     or    a            ; ... the TX Queue
  1631.     push    hl
  1632.     sbc    hl,de
  1633.     pop    hl
  1634.     jp    nz,TQI_0        ; go there if not at buffer bottom
  1635.  
  1636.     ld    hl,TX_Top        ; else reload with top of queue val
  1637. TQI_0:
  1638.     ld    (TX_Tail_CBuf),hl    ; save next free queue slot
  1639.     ld    hl,TX_Outstanding
  1640.     inc    (hl)            ; +1 more frame outstanding now
  1641.     pop    hl
  1642.     pop    de
  1643.     pop    af
  1644.     ret
  1645.  
  1646. ;-----------------------------------------------------------------------------
  1647. ; Setup HL & TX_Chain_Head for transmission of next chain.
  1648.  
  1649. TXnext_CBuf:
  1650.     push    af
  1651.     push    de
  1652.     ld    hl,(TX_Head_CBuf)
  1653.     ld    e,(hl)
  1654.     inc    hl
  1655.     ld    d,(hl)            ; DE -> next chain to transmit
  1656.     inc    hl            ; HL MIGHT be next CBuf entry pointer
  1657.     push    de
  1658.     ld    de,TX_Bottom
  1659.     or    a            ;clear carry
  1660.     push    hl            ;save what might be correct value
  1661.     sbc    hl,de
  1662.     pop    hl
  1663.     pop    de
  1664.     jp    nz,TXn_1        ;go there if not at end of circ. buf
  1665.  
  1666.     ld    hl,TX_Top        ;else we wrap aroune
  1667. TXn_1:
  1668.     ld    (TX_Head_CBuf),hl    ;save next circ buf pointer in mem
  1669.     ex    de,hl            ;return ptr to next chain to TX in HL
  1670.     ld    (TX_Chain_Head),hl    ;TX RCA routine needs this
  1671.     pop    de
  1672.     pop    af
  1673.     ret
  1674.  
  1675.  
  1676. ;-----------------------------------------------------------------------------
  1677. STA_on:        ;Turn the STA LED on.  ASSUMES that interrupts are disabled!
  1678.     push    af
  1679.     ld    a,5
  1680.     out    (A_ctl),a        ; ready to write WR5
  1681.     ld    a,(A_WR5)        ; get memory copy
  1682.     and    NOT ALED        ; set DTR bit to 0 so LED goes on
  1683.     out    (A_ctl),a        ; Actually turn on STA LED now...
  1684.     ld    (A_WR5),a        ; update memory copy
  1685.     pop    af
  1686.     ret
  1687. ;-----------------------------------------------------------------------------
  1688. STA_off:    ;Turn the STA LED off.  ASSUMES that interrupts are disabled!
  1689.     push    af
  1690.     ld    a,5
  1691.     out    (A_ctl),a        ; ready to write WR5
  1692.     ld    a,(A_WR5)        ; get memory copy
  1693.     or    ALED            ; set DTR bit to 1 so LED goes off
  1694.     out    (A_ctl),a        ; Actually turn off STA LED now...
  1695.     ld    (A_WR5),a        ; update memory copy
  1696.     pop    af
  1697.     ret
  1698.  
  1699. ;These routines MUST be called with interrupts disabled!
  1700. ;-----------------------------------------------------------------------------
  1701. STA_flip:
  1702.     push    af
  1703.     in    a,(A_ctl)        ;assure we are talking to ch 0
  1704.     ld    a,5
  1705.     out    (A_ctl),a        ; ready to write WR5
  1706.     ld    a,(A_WR5)        ; get memory copy
  1707.     xor    ALED            ; [JDZ]
  1708.     out    (A_ctl),a        ; Actually turn off STA LED now...
  1709.     ld    (A_WR5),a        ; update memory copy
  1710.     pop    af
  1711.     ret
  1712.     
  1713. ;-----------------------------------------------------------------------------
  1714. CON_on:
  1715.     push    af
  1716.     ld    a,5
  1717.     out    (B_ctl),a
  1718.     ld    a,BLEDon
  1719.     ld    (B_WR5),a        ; save in mem for flip routine
  1720.     out    (B_ctl),a
  1721.     pop    af
  1722.     ret
  1723. ;-----------------------------------------------------------------------------
  1724. CON_off:
  1725.     push    af
  1726.     ld    a,5
  1727.     out    (B_ctl),a
  1728.     ld    a,BLEDoff
  1729.     ld    (B_WR5),a        ; save in mem for flip routine
  1730.     out    (B_ctl),a
  1731.     pop    af
  1732.     ret
  1733. ;-----------------------------------------------------------------------------
  1734. CON_flip:
  1735.     push    af
  1736.     in    a,(B_ctl)        ;assure we are talking to ch 0
  1737.     ld    a,5
  1738.     out    (B_ctl),a        ; ready to write WR5
  1739.     ld    a,(B_WR5)        ; get memory copy
  1740.     xor    BLED            ; [JDZ]
  1741.     out    (B_ctl),a        ; Actually turn off CON LED now...
  1742.     ld    (B_WR5),a        ; update memory copy
  1743.     pop    af
  1744.     ret
  1745.  
  1746. ; SIO Initialize data.
  1747. a_init:
  1748.     db    18h,4,20h,1,1bh,7,7eh,5,ALEDoff,3,0c9h    ;For Modem
  1749. a_size    equ    $-a_init
  1750.  
  1751. b_init:                            ;[JDZ] For TTY
  1752.     db    18h,4,44h,2,I_Vector mod 256,3,Auto_Enable,5,BLEDoff,1,1fh
  1753. b_size    equ    $-b_init
  1754.  
  1755.  
  1756. ;This is the data area which gets blasted into RAM upon startup: [JDZ]
  1757. data_init:
  1758.  
  1759. TXdelay        equ    Free_RAM - data_init + $
  1760.         db    33        ; TX delay default is 330 ms
  1761. Persistence        equ    Free_RAM - data_init + $
  1762.         db    63        ; default value for Persistence
  1763. SlotTime        equ    Free_RAM - data_init + $
  1764.         db    5        ; and Slot Time defaults to 50 ms
  1765. TailTime        equ    Free_RAM - data_init + $
  1766.         db    3        ; (should be 11 for 300 baud)
  1767.                     ; Tail Timer default
  1768. Full_Duplex        equ    Free_RAM - data_init + $
  1769.         db    0        ;not Full Duplex to start
  1770. CTS_Control        equ    Free_RAM - data_init + $
  1771.         db    0        ;not CTS Control to start
  1772. Soft_DCD        equ    Free_RAM - data_init + $
  1773.         db    1        ;not Soft DCD to start
  1774.  
  1775. RX_State        equ    Free_RAM - data_init + $
  1776.         db    0        ;Means we are in Recieving State
  1777. RX_Allocated_Buffer    equ    Free_RAM - data_init + $
  1778.         db    0        ;set non-zero if we're in RX state
  1779. RX_buf            equ    Free_RAM - data_init + $
  1780.         dw    0        ;address of current Receive buffer
  1781. RX_head            equ    Free_RAM - data_init + $
  1782.         dw    0        ;address of 1st RX buffer
  1783. RX_Flushing        equ    Free_RAM - data_init + $
  1784.         db    0        ;is non-0 if we ran out of buffer
  1785.                     ;space and are currently flushing this
  1786.                     ;frame being received.  Used by
  1787.                     ;ia_rca and reset by ia_ext.
  1788.  
  1789. TX_State        equ    Free_RAM - data_init + $
  1790.         db    0        ;TX state.
  1791.                     ;0 : we're not in TX state
  1792.                     ;1 : we're in slot time state
  1793.                     ;2 : we're in TX delay state
  1794.                     ;3 : we're in waiting CTS is turn on
  1795.                     ;4 : we're in Transmit data state
  1796.                     ;5 : we're in Tail time state
  1797. TX_Started        equ    Free_RAM - data_init + $
  1798.         db    0        ;non-zero if we've begun TXing chars
  1799. TX_Outstanding        equ    Free_RAM - data_init + $
  1800.         db    0        ;Number of TX CBufs queued up for TX
  1801. TX_Head_CBuf        equ    Free_RAM - data_init + $
  1802.         dw    TX_Top    ;Current active CBuf entry (if active)
  1803. TX_Tail_CBuf        equ    Free_RAM - data_init + $
  1804.         dw    TX_Top    ;next free CBuf entry
  1805. TX_Chain_Head        equ    Free_RAM - data_init + $
  1806.         dw    0        ;holds address of the current buffer
  1807.                     ;chain head that we are transmitting
  1808. TX_Timer        equ    Free_RAM - data_init + $
  1809.         db    0
  1810.  
  1811. A_RR0        equ    Free_RAM - data_init + $
  1812.         db    CTS
  1813. A_WR5        equ    Free_RAM - data_init + $
  1814.         db    ALEDoff        ;state of STA LED & RTS (PTT) line,
  1815.                     ;mainly... (For Ch A only [modem] )
  1816. B_WR5        equ    Free_RAM - data_init + $
  1817.         db    BLEDoff
  1818. ;these next two are used by the IB_TBE interrupt routine.
  1819. Out_esc_mode        equ    Free_RAM - data_init + $
  1820.         db    0        ; not in escaped mode 
  1821. Out_char        equ    Free_RAM - data_init + $
  1822.         ds    1        ; next char to send if escaped mode
  1823. in_break        equ    Free_RAM - data_init + $
  1824.         db    0        ; non-zero if we are in a break detect
  1825.                     ; sequence on the async port
  1826. In_Buffer        equ    Free_RAM - data_init + $
  1827.         dw    0        ;addr of current Input buffer
  1828. In_Head            equ    Free_RAM - data_init + $
  1829.         dw    0        ;addr of 1st Input Buffer
  1830. In_Allocated_Buffer    equ    Free_RAM - data_init + $
  1831.         db    0        ;is not 0 if we've already alloc'd buf
  1832. In_State        equ    Free_RAM - data_init + $
  1833.         db    1        ;convert back to 1 in v.32 code
  1834.                     ;input state machine state
  1835.                     ;4 Mar 8: Make it 0 (from 1) becuz
  1836.                     ;noise on line is first triggering the
  1837.                     ;code to assume that a frame is coming
  1838.                     ;from the host.....  Comment below was
  1839.                     ;appropriate before
  1840.                     ;assume that we've seen an FEND from
  1841.                     ;(non-existent) "previous" frame. This
  1842.                     ;means that when we are receiving data
  1843.                     ;from user, there need be ONLY the
  1844.                     ;FEND char at the end of a frame, and
  1845.                     ;not at the beginning (although if a
  1846.                     ;FEND is at the beginning, it is 
  1847.                     ;ignored.)
  1848. Out_Started        equ    Free_RAM - data_init + $
  1849.         db    0        ;Output not started yet (Logical var)
  1850. Out_Head_CBuf        equ    Free_RAM - data_init + $
  1851.         dw    Out_Top        ;address of buffer to be output rs232
  1852. Out_Tail_CBuf        equ    Free_RAM - data_init + $
  1853.         dw    Out_Top        ;pointer to next free output buffer
  1854. Out_Chain_Head        equ    Free_RAM - data_init + $
  1855.         dw    0        ;addr of buffer we are now outputting
  1856. free            equ    Free_RAM - data_init + $
  1857.         dw    Bottom        ;address of 1st buffer on free list
  1858.  
  1859. data_size    equ    $-data_init
  1860.  
  1861. Out_Address    equ    free+2        ;address of output following data
  1862.         ;ds    1
  1863.  
  1864. buffer_area    equ    Out_Address+1
  1865.  
  1866. TX_Top        equ    buffer_area    ;"top" of output circular buffer
  1867.                     ; 255 out buffer chains pending, max
  1868. TX_Bottom    equ    TX_Top+2*255    ;"bottom" of output circular buffer
  1869.  
  1870.  
  1871. Out_Top        equ    TX_Bottom+2
  1872. Out_Bottom    equ    Out_Top+2*255
  1873.  
  1874.  
  1875. Bottom        equ    Out_Bottom+2    ;end of all code & predefined data
  1876.  
  1877. ;***************************************************************************
  1878.  
  1879. ;    out = to TTY port; in = from TTY port
  1880. ;    TX = to modem; RX = from modem
  1881. ;
  1882. ;    ; means that that code executes without interrupts enabled (except
  1883. ;        for the initialization code)
  1884.  
  1885.     end    start
  1886.